package data

import (
	conf "admin_template/bff/admin/internal/base/config"
	"admin_template/bff/admin/internal/entity/ent"
	"admin_template/bff/admin/internal/pkg/utils"
	"context"
	"entgo.io/ent/dialect/sql/schema"
	"gitee.com/byx_darwin/go-tools/tools/entutils"
	"github.com/casbin/casbin/v2"
	"github.com/casbin/casbin/v2/model"
	entadapter "github.com/casbin/ent-adapter"
	"github.com/cloudwego/hertz/pkg/app"
	"github.com/cloudwego/hertz/pkg/common/hlog"
)

type Data struct {
	Config    *conf.Config
	CtxLogger hlog.CtxLogger
	DB        *ent.Client
	Enforcer  *casbin.CachedEnforcer
}

func NewData(log hlog.CtxLogger, config *conf.Config) (*Data, func(), error) {
	ctx := context.Background()
	return &Data{
			Config:    config,
			CtxLogger: log,
			DB:        newDB(ctx, config, log),
			Enforcer:  newEnforcer(config),
		}, func() {

		}, nil
}

func (data *Data) WithConfig(c *conf.Config) {
	data.Config = c
}

func newDB(ctx context.Context, conf *conf.Config, log hlog.CtxLogger) *ent.Client {
	entMysqlDriver, err := entutils.NewDriver(ctx, &conf.DBOption,
		conf.ServerOption.Jaeger.Enable, log)
	if err != nil {
		log.CtxFatalf(ctx, "entutils NewDriver failure,err: %v", err)
	}
	dbClient := ent.NewClient(ent.Driver(entMysqlDriver))
	// Run the auto migration tool.
	if err := dbClient.Schema.Create(ctx, schema.WithForeignKeys(false)); err != nil {
		log.CtxFatalf(ctx, "failed update schema resources: %v", err)
	}
	return dbClient
}

func newEnforcer(conf *conf.Config) *casbin.CachedEnforcer {
	a, err := entadapter.NewAdapter(conf.DBOption.Driver, conf.DBOption.Source)
	if err != nil {
		panic(err)
	}
	text := `
		[request_definition]
		r = sub, obj, act
		[policy_definition]
		p = sub, obj, act
		
		[role_definition]
		g = _, _
		
		[policy_effect]
		e = some(where (p.eft == allow))
		
		[matchers]
		m = r.sub == p.sub && keyMatch2(r.obj,p.obj) && r.act == p.act
		`
	m, err := model.NewModelFromString(text)
	if err != nil {
		panic(err)
	}
	cachedEnforcer, _ := casbin.NewCachedEnforcer(m, a)
	_ = cachedEnforcer.LoadPolicy()
	return cachedEnforcer
}
func (data *Data) UserUUID(ctx *app.RequestContext) string {
	return utils.GetUserToken(ctx).UUID
}

func (data *Data) RoleID(ctx *app.RequestContext) int64 {
	return utils.GetUserToken(ctx).RoleID
}
